package jehc.djshi.oauth.web;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import jehc.djshi.common.annotation.AuthUneedLogin;
import jehc.djshi.common.base.BaseAction;
import jehc.djshi.common.base.BaseHttpSessionEntity;
import jehc.djshi.common.base.BaseResult;
import jehc.djshi.common.constant.CacheConstant;
import jehc.djshi.common.constant.PathConstant;
import jehc.djshi.common.constant.SessionConstant;
import jehc.djshi.common.constant.StatusConstant;
import jehc.djshi.common.entity.InputEntity;
import jehc.djshi.common.entity.OauthAccountEntity;
import jehc.djshi.common.entity.OauthAdminSysEntity;
import jehc.djshi.common.entity.index.*;
import jehc.djshi.common.session.HttpSessionUtils;
import jehc.djshi.common.util.JsonUtil;
import jehc.djshi.common.util.SortUtil;
import jehc.djshi.common.util.StringUtil;
import jehc.djshi.oauth.util.OauthUtil;
import jehc.djshi.oauth.model.OauthKeyInfo;
import jehc.djshi.oauth.model.OauthResources;
import jehc.djshi.oauth.model.OauthSysModules;
import jehc.djshi.oauth.service.OauthResourcesService;
import jehc.djshi.oauth.service.OauthSysModulesService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.*;
/**
 * @Desc 授权中心API
 * @Author 邓纯杰
 * @CreateTime 2012-12-12 12:12:12
 */
@RestController
@Api(value = "授权中心API",tags = "授权中心API",description = "授权中心API")
public class OauthController extends BaseAction {
    @Autowired
    private OauthUtil oauthUtil;

    @Autowired
    HttpSessionUtils httpSessionUtils;

    @Autowired
    private OauthResourcesService oauthResourcesService;
    @Autowired
    private OauthSysModulesService oauthSysModulesService;

    /**
     * 验证权限
     * @param request
     */
    @AuthUneedLogin
    @PostMapping(value="/oauth")
    @ApiOperation(value="验证权限", notes="验证权限")
    public BaseResult oauth(HttpServletRequest request, @RequestBody InputEntity inputEntity){
        long beginTime = System.currentTimeMillis();
        Long endTime = 0L;
        BaseResult baseResult = validateSysMode(request);
        if(!baseResult.getSuccess()){
            return baseResult;
        }
        ///////////////////拦截IP黑户开始（优先级最高）///////////////////////
//        if(!validateIP(request)) {
//            if(!bDownLoad(request)){
//                return outAudStr(false,  StatusConstant.BDOWNFLAG_TEXT);
//            }
//            return new BaseResult(StatusConstant.XT_PT_STATUS_VAL_001,null,false);
//        }
        ///////////////////拦截IP黑户结束///////////////////////
        String requestUrl = inputEntity.getUrl();
        if(requestUrl.equals(PathConstant.REQUEST_ERROR)){
            return outAudStr(false, "Request exception");
        }
        endTime = System.currentTimeMillis();
        System.out.println("授权中心3："+(endTime-beginTime)+" ms");
        //不需要登陆验证的URL
        //需要登录验证的URL（目前不使用该注解 若authUneedLogin不需要登录不满足 则其下所有方法必须默认为需登录条件）
//		AuthNeedLogin authNeedLogin=methodHandler.getMethodAnnotation(AuthNeedLogin.class);
        //如果获取到方法是无需登录则放开 让其走（优先级第二）
        if(!StringUtil.isEmpty(inputEntity.getAuthUneedLogin())){
            return outAudStr(true, "AuthUneedLogin---Success");
        }
        //过滤druid
        if(((request.getRequestURI().indexOf(("druid"))> 0 ) && null == baseUtils.getXtU())){
            return new BaseResult(StatusConstant.XT_PT_STATUS_VAL_888,"druid被访问时，session不存在",false);
        }
        endTime = System.currentTimeMillis();
        System.out.println("授权中心2："+(endTime-beginTime)+" ms");
        //需要登录但无需拦截验证URL
        if(!StringUtil.isEmpty(inputEntity.getNeedLoginUnAuth())){
            OauthAccountEntity oauthAccountEntity = baseUtils.getXtU();
            //如果注解为需要用户登录 则判断该用户是否登录 如果登录了 则放开其操作该方法的权限 否则不通过
            if(null == oauthAccountEntity){
                return new BaseResult(StatusConstant.XT_PT_STATUS_VAL_888,"session不存在",false);
            }else{
                updateExpire(oauthUtil.getTokenByAccountId(oauthAccountEntity.getAccount_id()),oauthAccountEntity.getAccount_id(),oauthUtil.getTokenInfo(request));//更新Token有效期（如果一直活跃则更新有效期，否则到期直接失效）
                return outAudStr(true, "NeedLoginUnAuth---Success");
            }
        }
        //验证当前用户是否登录（优先级第三）
        OauthAccountEntity oauthAccountEntity = baseUtils.getXtU();
        if(null == oauthAccountEntity){
            //未登陆Token不存在
            return new BaseResult(StatusConstant.XT_PT_STATUS_VAL_888,"登陆会话失效",false);
        }
        endTime = System.currentTimeMillis();
        System.out.println("授权中心1："+(endTime-beginTime)+" ms");
        //////////////////对功能进行拦截开始///////////////////
        updateExpire(oauthUtil.getTokenByAccountId(oauthAccountEntity.getAccount_id()),oauthAccountEntity.getAccount_id(),oauthUtil.getTokenInfo(request));//更新Token有效期（如果一直活跃则更新有效期，否则到期直接失效）
        /*
        //过滤公共功能
        String XtFunctioninfoCommon = BaseUtils.getXtFunctioninfoCommonCache();
        if(!StringUtils.isEmpty(XtFunctioninfoCommon) && XtFunctioninfoCommon.indexOf(","+requestUrl+",") >= 0){
            return this.dataAuth(request, requestUrl,baseHttpSessionEntity);
        }
        */
        endTime = System.currentTimeMillis();
        System.out.println("授权中心："+(endTime-beginTime)+" ms");
        //如果超级管理员则放过所有功能
        if(baseUtils.isAdmin()){
            return outAudStr(true, "Admin---Success");
        }
        BaseHttpSessionEntity baseHttpSessionEntity = baseUtils.getBaseHttpSessionEntity();
        //非超级管理员则进行功能权限验证
        Map<String,String> oauthFunctionInfoUrlMap = baseHttpSessionEntity.getOauthFunctionInfoUrlMap();
        if(null == oauthFunctionInfoUrlMap.get(requestUrl)){
            //如果非附件操作权限
            return new BaseResult(StatusConstant.XT_PT_STATUS_VAL_777,"无权限",false);
        }else{
            return dataAuth(request, requestUrl,baseHttpSessionEntity);
        }
        //////////////////对功能进行拦截结束///////////////////
    }

//
//    /**
//     * 统一输出内容
//     * @param request
//     * @param response
//     * @param status
//     * @param msg
//     */
//    public void write(HttpServletRequest request, HttpServletResponse response,int status,String msg){
//        try {
//            logger.debug("拦截器输出日志开始");
//            response.setContentType("application/json;charset=utf-8");
//            PrintWriter writer = response.getWriter();
//            BaseResult baseResult = new BaseResult();
//            baseResult.setStatus(StatusConstant.XT_PT_STATUS_VAL_888);
//            baseResult.setMessage(msg);
//            JSONObject json = JsonUtil.toJsonObj(baseResult);
//            writer.write(json.toString());
//            writer.flush();
//            logger.debug("拦截器输出日志结束");
//        } catch (IOException e) {
//            logger.debug("拦截器输出日志,操作出现异常，IOException:"+e.getMessage());
//        }
//    }

//    /**
//     * 是否能够下载文件（jquery模式 非extjs模式）
//     * @param request
//     * @return
//     */
//    public boolean bDownLoad(HttpServletRequest request){
//        String bdownflag = request.getParameter(StatusConstant.BDOWNFLAG);
//        if(!StringUtils.isEmpty(bdownflag)){
//            return false;
//        }
//        return true;
//    }
//    /**
//     * 判断IP是否合法 合法true 不合法false
//     * @param request
//     * @return
//     */
//    public boolean validateIP(HttpServletRequest request){
//        String ip = request.getRemoteAddr();
//        boolean flag = BaseUtils.getXtIpFrozenCache(ip);
//        return flag;
//    }


    /**
     * 处理数据权限
     * @param request
     * @param requestUrl
     * @return
     * @throws IOException
     */
    public BaseResult dataAuth(HttpServletRequest request,String requestUrl, BaseHttpSessionEntity baseHttpSessionEntity){
        String[] paramNames = (String[])request.getParameterValues("systemUID");//唯一标志systemUID
        List<String> systemUandM = baseHttpSessionEntity.getSystemAM();
        List<String> sysUID = new ArrayList<String>();
        //如果系统唯一标志不为空 说明系统采用了数据权限
        if(null != paramNames){
            //参数组成的数组
            String systemUID = paramNames[0];
            String[] systemUIDarray = new String[]{};
            if(null != systemUID && !"".equals(systemUID)){
                systemUIDarray = systemUID.split(",");
            }
            if(null != systemUandM){
                int result = 0;
                for(String str:systemUandM){
                    String[] sysUandMarray = new String[]{};
                    if(!StringUtil.isEmpty(str)){
                        sysUandMarray = str.split("#");
                        if(null != sysUandMarray){
                            //判断方法和参数都匹配
                            if(("@"+sysUandMarray[1]+"@").indexOf("@"+requestUrl+"@") >= 0){
                                for(int j = 0; j<systemUIDarray.length;j++){
                                    if(sysUandMarray[0].equals(systemUIDarray[j])){
                                        //如果相等
                                        result = result+1;
                                    }
                                }
                            }
                        }
                    }
                }
                //如果参数全部符合则进入方法
                if(result != systemUIDarray.length){
                    //没有权限操作
                    return new BaseResult("您没有该操作权限,请与管理员联系!",false);
                }
            }
        }else{
            //否则过滤当前操作是否数据权限查询拦截
            //说明可能是第一次初始化读取数据
            if(null != systemUandM){
                for(String str: systemUandM){
                    String[] sysUandMarray = new String[]{};
                    if(!StringUtil.isEmpty(str)){
                        sysUandMarray = str.split("#");
                        if(("@"+sysUandMarray[1]+"@").indexOf("@"+requestUrl+"@") >= 0){
                            sysUID.add(sysUandMarray[0]);
                        }
                    }
                }
                request.setAttribute("sysUID", sysUID);//用户ID
            }
        }
        return new BaseResult("dataAuth----success!",true);
    }


    /**
     * 获取token信息
     *
     * @return
     */
    @ApiOperation(value="Token信息", notes="Token信息")
    @GetMapping(value="/tokenInfo")
    public BaseHttpSessionEntity tokenInfo(HttpServletRequest request) {
        String info = oauthUtil.getTokenInfo(request);
        BaseHttpSessionEntity baseHttpSessionEntity = JsonUtil.fromAliFastJson(info, BaseHttpSessionEntity.class);
        return baseHttpSessionEntity;
    }

    /**
     * 根据token字符串获取token信息
     *
     * @return
     */
    @ApiOperation(value="Token信息", notes="Token信息")
    @GetMapping(value="/tokenInfoByToken")
    @AuthUneedLogin
    public BaseHttpSessionEntity tokenInfo(String token) {
        String info = oauthUtil.getTokenInfo(token);
        BaseHttpSessionEntity baseHttpSessionEntity = JsonUtil.fromAliFastJson(info, BaseHttpSessionEntity.class);
        return baseHttpSessionEntity;
    }

    /**
     *  获取resources
     * @param request
     * @return
     */
    @PostMapping(value="/resource")
    @ApiOperation(value="获取资源列表", notes="获取资源列表")
//	@HystrixCommand(fallbackMethod = "initFB")//熔断器需要追加fallbackMethod才可监控
    public BaseResult init(HttpServletRequest request){
        String info = oauthUtil.getTokenInfo(request);
        BaseHttpSessionEntity baseHttpSessionEntity = JsonUtil.fromAliFastJson(info, BaseHttpSessionEntity.class);
        String oauthAdminSysEntity = baseHttpSessionEntity.getOauthAdminSysEntities();
        List<OauthAdminSysEntity> oauthAdminSysEntities = JsonUtil.toFastList(oauthAdminSysEntity, OauthAdminSysEntity.class);

        List<OauthResources> oauthResourcesList = null;
        List<String> idList = commonSysModulesId(oauthAdminSysEntities);
        Map<String, Object> condition = new HashMap<String, Object>();
        if(null != idList && !idList.isEmpty()){
            //各子系统管理员
            condition.put("resources_module_id",idList);
            oauthResourcesList = oauthResourcesService.getOauthResourcesListByCondition(condition);
        }else{
            //各子系统角色
            if(null == baseHttpSessionEntity){
                condition.put("role_id", "-1".split(","));
            }else{
                String xt_role_id = baseHttpSessionEntity.getRole_id();
                if(!StringUtils.isEmpty(xt_role_id)){
                    condition.put("role_id", xt_role_id.split(","));
                }else{
                    condition.put("role_id", "-1".split(","));
                }
            }
            oauthResourcesList = oauthResourcesService.getResourcesListForRole(condition);
        }

        InitAdminPage initAdminPage = new InitAdminPage();

        SortUtil<OauthResources> sortUtil = new SortUtil<OauthResources>();

        sortUtil.Sort(oauthResourcesList, "resources_sort", "asc");

        String json = JsonUtil.toFastJson(oauthResourcesList);

        List<ResourceEntity> resourceEntities = JsonUtil.toFList(json, ResourceEntity.class);

        Map<String,List<ResourceEntity>> map = commonResourceEntities(resourceEntities);//转换资源集合

        if(!CollectionUtils.isEmpty(map)){
            Iterator<Map.Entry<String, List<ResourceEntity>>> entries = map.entrySet().iterator();
            while (entries.hasNext()) {
                Map.Entry<String, List<ResourceEntity>> entry = entries.next();
                IndexTree tree = new IndexTree(entry.getValue());
                MenuEntity menuEntity = new MenuEntity();
                menuEntity.setSys_mode_id(entry.getKey());
                menuEntity.setSys_mode_icon(entry.getValue().get(0).getSys_mode_icon());
                menuEntity.setSysname(entry.getValue().get(0).getSysname());
                menuEntity.setSys_mode_url(entry.getValue().get(0).getSys_mode_url());
                menuEntity.setMenuList(tree.buildTree(false));
                initAdminPage.getMenuEntity().add(menuEntity);
            }
        }

        AdminTree adminTree = new AdminTree(resourceEntities);
        initAdminPage.setAdminMenuList(adminTree.buildTree());

        initAdminPage.setBasePath(request.getContextPath());

        initAdminPage.setOauthAccountEntity(getXtU());//当前用户

        return outDataStr(initAdminPage);
    }

    /**
     *
     * @param resourceEntities
     */
    public  Map<String,List<ResourceEntity>> commonResourceEntities(List<ResourceEntity> resourceEntities){
        Map<String,List<ResourceEntity>> map = new HashMap<>();
        if(null!=resourceEntities && !resourceEntities.isEmpty()){
            for(ResourceEntity resourceEntity:resourceEntities){
                List<ResourceEntity> resourceEntityList = map.get(resourceEntity.getSys_mode_id());
                if(null == resourceEntityList || resourceEntityList.isEmpty()){
                    resourceEntityList =  new ArrayList<>();
                }
                resourceEntityList.add(resourceEntity);
                map.put(resourceEntity.getSys_mode_id(),resourceEntityList);
            }
        }
        return map;
    }

    /**
     *
     * @param oauthAdminSysEntities
     * @return
     */
    public List<String> commonSysModulesId(List<OauthAdminSysEntity> oauthAdminSysEntities){
        List<String> idList = new ArrayList<>();
        List<String> sysmodeIdList = new ArrayList<>();
        if(oauthAdminSysEntities == null || oauthAdminSysEntities.isEmpty() || oauthAdminSysEntities.size() == 0){
            return idList;
        }
        for(OauthAdminSysEntity oauthAdminSysEntity : oauthAdminSysEntities){
            sysmodeIdList.add(oauthAdminSysEntity.getSysmode_id());
        }
        if(null == sysmodeIdList || sysmodeIdList.isEmpty() || sysmodeIdList.size() == 0){
            return idList;
        }

        Map<String,Object> condition = new HashMap<>();
        condition.put("sysmode_id",sysmodeIdList);
        List<OauthSysModules> oauthSysModulesList = oauthSysModulesService.getOauthSysModulesListByCondition(condition);
        for(OauthSysModules oauthSysModules:oauthSysModulesList){
            idList.add(oauthSysModules.getSys_modules_id());
        }
        return idList;
    }

    /**
     * 验证SysMode是否合法
     * @param request
     * @return
     */
    private BaseResult validateSysMode(HttpServletRequest request){
        String key = null;
        String pass = null;
        Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String k = (String) headerNames.nextElement();
            if(k.toLowerCase().equals(CacheConstant.JEHC_CLOUD_KEY.toLowerCase())){
                key = request.getHeader(k);
            }
            if(k.toLowerCase().equals(CacheConstant.JEHC_CLOUD_SECURITY.toLowerCase())){
                pass = request.getHeader(k);
            }
        }
        if(StringUtil.isEmpty(key)){
            return new BaseResult(StatusConstant.XT_PT_STATUS_VAL_999,"未能获取到平台Key",false);
        }
        if(StringUtil.isEmpty(pass)){
            return new BaseResult(StatusConstant.XT_PT_STATUS_VAL_999,"未能获取到平台秘钥",false);
        }
        String oauthKeyInfoJson = httpSessionUtils.getHashAttribute(CacheConstant.OAUTH_KEY,key);
        OauthKeyInfo oauthKeyInfo = JsonUtil.fromFJson(oauthKeyInfoJson,OauthKeyInfo.class);
        if(null == oauthKeyInfo || StringUtil.isEmpty(oauthKeyInfo.getKey_pass())){
            return new BaseResult(StatusConstant.XT_PT_STATUS_VAL_999,"平台秘钥不存在",false);
        }
        String key_pass = oauthKeyInfo.getKey_pass();
        if(!pass.equals(key_pass)){
            return new BaseResult(StatusConstant.XT_PT_STATUS_VAL_999,"平台秘钥不正确",false);
        }
        return new BaseResult(StatusConstant.XT_PT_STATUS_VAL_200,"平台秘钥合法",true,key);
    }


    /**
     *  如果一直活跃更新Token失效时间
     * @param token
     * @param tokenInfo
     */
    public void updateExpire(String token,String clientId,String tokenInfo){
        if(httpSessionUtils.setAttributeExpTime(SessionConstant.TOKEN_STORE_PATH+token, tokenInfo,12)){
            httpSessionUtils.setAttributeExpTime(SessionConstant.ACCOUNT_STORE_PATH+clientId, token,12);//单独存放Account编号维护Token
        }
    }

    /**
     * 根据account_id查找在线用户Token
     *
     * @return
     */
    @ApiOperation(value="Token值", notes="Token值")
    @GetMapping(value="/tokenByAccountId")
    @AuthUneedLogin
    public BaseResult tokenByAccountId(String account_id) {
        String info = oauthUtil.getTokenByAccountId(account_id);
        return new BaseResult(info);
    }
}

